// 用局部锁来实现
#include <iostream>
#include <unistd.h>
#include <thread>

using namespace std;

int tickets = 10000;

// 主线程给新线程传参所用的类
class TData
{
public:
    TData(const string &name, pthread_mutex_t *pmutex)
        : _name(name), _pmutex(pmutex)
    {
    }
    ~TData()
    {
    }

public:
    string _name;
    pthread_mutex_t *_pmutex;
};

void *threadRoutine(void *args)
{
    TData *td = static_cast<TData *>(args);

    while (true)
    {
        pthread_mutex_lock(td->_pmutex); // 所有的线程都需要先上锁才能再访问资源
        if (tickets > 0)
        {
            usleep(2000); // 模拟抢票花费的时间
            printf("td:%p  ", td);
            cout << td->_name << "get a ticket:" << tickets-- << endl;
            pthread_mutex_unlock(td->_pmutex);
        }
        else
        {
            pthread_mutex_unlock(td->_pmutex);
            break;
        }
        // pthread_mutex_unlock(&mutex);//解锁不能放在这里，如果票数<0执行break会漏掉解锁
        usleep(1000); // 抢完票的后续动作
    }
    return nullptr;
}

int main()
{
    pthread_mutex_t mutex; // 一个局部锁

    pthread_mutex_init(&mutex, nullptr);

    pthread_t tids[4];
    int n = sizeof(tids) / sizeof(tids[0]);

    // 让所有线程访问公共的局部锁
    for (int i = 0; i < n; i++)
    {
        char name[64];
        snprintf(name, 64, "thread-%d  ", i + 1);
        TData *td = new TData(name, &mutex); // 每个线程中都有一个TData对象，这些对象都指向相同的局部锁
        pthread_create(tids + i, nullptr, threadRoutine, td);
    }

    for (int i = 0; i < n; i++)
    {
        pthread_join(tids[i], nullptr);
    }

    pthread_mutex_destroy(&mutex);
}